package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private AlbumInfoService albumInfoService;
    @Autowired
    private UserInfoFeignClient userInfoFeignClient;
    @Autowired
    private TrackStatMapper trackStatMapper;
    @Autowired
    private VodService vodService;


    @Override
    public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> trackListVoPage, TrackInfoQuery trackInfoQuery) {
        return trackInfoMapper.selectUserTrackPage(trackListVoPage, trackInfoQuery);
    }

    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> pageParam, Long albumId, Long userId) {
        //	根据专辑Id 获取到声音集合
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectAlbumTrackPage(pageParam, albumId);

        //	判断用户是否需要付费：0101-免费 0102-vip付费 0103-付费
        AlbumInfo albumInfo = albumInfoService.getById(albumId);
        Assert.notNull(albumInfo, "专辑对象不能为空");
        //	判断用户是否登录
        if (null == userId) {
            //	除免费的专辑都需要显示付费表示
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                //	处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)) {
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //	显示付费通知
                        albumTrackListVo.setIsShowPaidMark(true);
                    });
                }
            }
        } else {
            //	用户已登录
            //	声明变量是否需要付费，默认不需要付费
            boolean isNeedPaid = false;
            //  vip 付费情况
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())) {
                //	获取用户信息
                Result<UserInfoVo> userInfoVoResult = userInfoFeignClient.getUserInfoVo(userId);
                Assert.notNull(userInfoVoResult, "用户信息不能为空");
                UserInfoVo userInfoVo = userInfoVoResult.getData();
                //	1.	VIP 免费,如果不是vip则需要付费，将这个变量设置为true，需要购买
                if (userInfoVo.getIsVip().intValue() == 0) {
                    isNeedPaid = true;
                }
                //1.1 如果是vip但是vip过期了（定时任务还为更新状态）
                if (userInfoVo.getIsVip().intValue() == 1 && userInfoVo.getVipExpireTime().before(new Date())) {
                    isNeedPaid = true;
                }
            } else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
                //	2.	付费
                isNeedPaid = true;
            }
            //需要付费，判断用户是否购买过专辑或声音
            if (isNeedPaid) {
                //	处理试听声音，获取需要付费的声音列表
                List<AlbumTrackListVo> albumTrackNeedPaidListVoList = pageInfo.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum().intValue() > albumInfo.getTracksForFree()).collect(Collectors.toList());
                //	判断
                if (!CollectionUtils.isEmpty(albumTrackNeedPaidListVoList)) {
                    //	判断用户是否购买该声音
                    //	获取到声音Id 集合列表
                    List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
                    //	获取用户购买的声音列表
                    Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
                    Assert.notNull(mapResult, "声音集合不能为空.");
                    Map<Long, Integer> map = mapResult.getData();
                    Assert.notNull(map, "map集合不能为空.");
                    albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
                        //	如果map.get(albumTrackListVo.getTrackId()) == 1 已经购买过，则不显示付费标识;
                        boolean isBuy = map.get(albumTrackListVo.getTrackId()) == 1 ? false : true;
                        albumTrackListVo.setIsShowPaidMark(isBuy);
                    });
                }
            }
        }
        // 返回集合数据
        return pageInfo;
    }

    @Transactional
    @Override
    public void updateStat(Long albumId, Long trackId, String statType, Integer count) {
        //	更新声音播放量
        trackInfoMapper.updateStat(trackId, statType, count);
        //	更新专辑播放量
        if (statType.equals(SystemConstant.TRACK_STAT_PLAY)) {
            albumInfoService.updateStat(albumId, SystemConstant.ALBUM_STAT_PLAY, count);
        }
    }

    //删除声音
    @Transactional
    @Override
    public void removeTrackInfo(Long id) {
        //# 1 把声音所在的专辑里面包含声音数量值-1 album_info
        // 根据专辑id查询声音所在的专辑数据
        // 根据声音id获取专辑id
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        Long albumId = trackInfo.getAlbumId();

        // 根据专辑id获取专辑数据
        AlbumInfo albumInfo = albumInfoService.getById(albumId);
        // 获取包含声音数量 -1
        Integer newInclueCount = albumInfo.getIncludeTrackCount() - 1;
        albumInfo.setIncludeTrackCount(newInclueCount);

        //调用方法修改
        albumInfoService.updateById(albumInfo);

        //# 2 根据声音id删除track_info表数据
        trackInfoMapper.deleteById(id);

        //# 3 根据声音id删除track_stat表数据
        LambdaQueryWrapper<TrackStat> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackStat::getTrackId, id);
        trackStatMapper.delete(wrapper);

        //# 4 删除腾讯云声音文件
        // 调用腾讯云接口实现
        vodService.removeTrackInfo(trackInfo.getMediaFileId());
    }

    //修改声音
    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //1 根据声音id获取声音数据
        TrackInfo trackInfo = trackInfoMapper.selectById(id);

        //获取声音文件fieldid
        String mediaFileId_database = trackInfo.getMediaFileId();

        BeanUtils.copyProperties(trackInfoVo, trackInfo);

        //比较数据库里面mediaFileId 和 页面传递 mediaFileId是否相同
        String mediaFileId_page = trackInfoVo.getMediaFileId();
        if (!mediaFileId_database.equals(mediaFileId_page)) {
            //获取最新声音文件数据
            TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackInfoTenx(mediaFileId_page);

            trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
            trackInfo.setMediaType(trackMediaInfoVo.getType());
            trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
            trackInfo.setMediaSize(trackMediaInfoVo.getSize());

            // 删除云点播声音
            vodService.removeTrackInfo(mediaFileId_database);
        }

        trackInfoMapper.updateById(trackInfo);
    }

    //保存声音
    @Transactional
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo, long userId) {
        //#1 添加声音基本信息 track_info
        //## 第一部分 -- 声音基本信息：专辑id、用户id、标题、简介、封面等等
        TrackInfo trackInfo = new TrackInfo();
        // trackInfoVo -- trackInfo
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        //其他值
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        trackInfo.setUserId(userId);

        //## 第二部分数据 -- 到腾讯云找到，声音文件信息，大小、播放时长、类型
        //声音文件在腾讯云存储唯一标识
        String mediaFileId = trackInfoVo.getMediaFileId();
        //根据mediaFileId调用腾讯云对应接口获取声音文件信息
        TrackMediaInfoVo trackMediaInfoVo = vodService.getTrackInfoTenx(mediaFileId);
        // 赋值声音
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
        trackInfo.setMediaType(trackMediaInfoVo.getType());

        //## 第三部分数据 -- order_num，声音排序字段，每次添加声音，值+1
        //		# track_info 根据专辑id获取专辑里面声音最大order_num
        //		select order_num from track_info info where info.album_id=1
        //		order by order_num desc limit 1
        LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId());
        wrapper.orderByDesc(TrackInfo::getOrderNum);
        wrapper.last(" limit 1");
        TrackInfo preTrackInfo = trackInfoMapper.selectOne(wrapper);
        Integer newOrder_num = 1;
        if (preTrackInfo != null) {
            newOrder_num = preTrackInfo.getOrderNum() + 1;
        }
        trackInfo.setOrderNum(newOrder_num);
        //调用方法添加 track_info
        trackInfoMapper.insert(trackInfo);

        //#2 track_stat
        //## -- 每个声音有四个统计数据，四个统计数据初始化0
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), "0702");
        this.saveTrackStat(trackInfo.getId(), "0703");
        this.saveTrackStat(trackInfo.getId(), "0704");

        //#3 album_info
        //## -- 修改操作，把声音所在专辑，include_track_count包含声音数量+1
        //根据专辑id查询专辑数据
        //获取声音数量值 + 1
        //调用方法修改
        AlbumInfo albumInfo = albumInfoService.getById(trackInfo.getAlbumId());
        int includeTrackCount = albumInfo.getIncludeTrackCount() + 1;
        albumInfo.setIncludeTrackCount(includeTrackCount);
        albumInfoService.updateById(albumInfo);
    }

    @Override
    public List<Map<String, Object>> findUserTrackPaidList(Long trackId) {
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoService.getById(albumId);

        Result<List<Long>> result = userInfoFeignClient.findUserPaidTrackList(albumId);
        List<Long> userPaidTrackIdList = result.getData();
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getAlbumId, albumInfo).gt(TrackInfo::getOrderNum, trackInfo.getOrderNum()));
        List<Long> trackIdAllList = trackInfoList.stream().map(TrackInfo::getId).collect(Collectors.toList());

        List<Long> trackIdNoReaptList = new ArrayList<>();

        if (CollectionUtils.isEmpty(userPaidTrackIdList)) {
            trackIdNoReaptList = trackIdAllList;
        } else {
            //把所有声音id集合遍历，得到每个声音id
            //拿着每个声音id到购买声音id集合判断，是否包含，如果不包含获取出来
            trackIdNoReaptList = trackIdAllList.stream().filter(itemId -> !userPaidTrackIdList.contains(itemId)).collect(Collectors.toList());
        }
        //5 封装集数  trackIdNoReaptList
        List<Map<String, Object>> list = new ArrayList();

        //封装本集
        if (trackIdNoReaptList.size() >= 0) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "本集");
            map.put("price", albumInfo.getPrice());
            map.put("trackCount", 0);
            list.add(map);
        }
        //trackIdNoReaptList > 0  <10情况
        // 1 2 3 4 5 6 7 8  本集  后7集
        if (trackIdNoReaptList.size() > 0 && trackIdNoReaptList.size() <= 10) {
            Map<String, Object> map = new HashMap<>();
            map.put("name", "后" + trackIdNoReaptList.size() + "集");
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }

        //trackIdNoReaptList > 10
        // 1 2 3 4 5 6 7 8 9 10 11   12  本集  后10集
        if (trackIdNoReaptList.size() > 10) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10));
            map.put("name", "后10集");
            map.put("price", price);
            map.put("trackCount", 10);
            list.add(map);
        }

        // 后20集
        if (trackIdNoReaptList.size() > 10 && trackIdNoReaptList.size() <= 20) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后" + count + "集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if (trackIdNoReaptList.size() > 20) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20));
            map.put("name", "后20集");
            map.put("price", price);
            map.put("trackCount", 20);
            list.add(map);
        }

        //后30集
        if (trackIdNoReaptList.size() > 20 && trackIdNoReaptList.size() <= 30) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后" + count + "集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        if (trackIdNoReaptList.size() > 30) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(30));
            map.put("name", "后30集");
            map.put("price", price);
            map.put("trackCount", 30);
            list.add(map);
        }

        //后50集
        if (trackIdNoReaptList.size() > 30 && trackIdNoReaptList.size() <= 50) {
            Map<String, Object> map = new HashMap<>();
            int count = trackIdNoReaptList.size();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(count));
            map.put("name", "后" + count + "集");
            map.put("price", price);
            map.put("trackCount", count);
            list.add(map);
        }
        // 最多购买50集;
        if (trackIdNoReaptList.size() > 50) {
            Map<String, Object> map = new HashMap<>();
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50));
            map.put("name", "后50集");
            map.put("price", price);
            map.put("trackCount", 50);
            list.add(map);
        }
        //返回
        return list;
    }

    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        //1 根据声音id获取声音数据（本集）
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

        Result<List<Long>> userPaidTrackListResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());

        List<Long> paidTrackIdList = userPaidTrackListResult.getData();

        List<TrackInfo> list = new ArrayList<>();
        // 判断:trackCount=0本集，trackCount>0后几集
        if (trackCount > 0) {
            //3 封装查询条件，查询专辑里面可以购买声音
            //专辑id
            //大于本集声音 orderNum
            //声音id不再购买过声音id列表里面  notIn
            //limit trackCount
            LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<TrackInfo>()
                    .eq(TrackInfo::getAlbumId, trackInfo.getAlbumId())
                    .gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());

            if (!CollectionUtils.isEmpty(paidTrackIdList)) {
                wrapper.notIn(TrackInfo::getId, paidTrackIdList);
            }
            wrapper.last(" limit " + trackCount);
            List<TrackInfo> trackInfos = trackInfoMapper.selectList(wrapper);

        }else {
            list.add(trackInfo);
        }
        return list;
    }


    /**
     * 初始化统计数量
     *
     * @param trackId
     * @param trackType
     */
    private void saveTrackStat(Long trackId, String trackType) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(trackId);
        trackStat.setStatType(trackType);
        trackStat.setStatNum(0);
        this.trackStatMapper.insert(trackStat);
    }
}
